// Utils.h
// 
// Copyright (c) Jason Sandys, 2009
//
// License: This code is released according to the 
// Microsoft Public License (Ms-PL) as documented at 
// http://osdappchooser.codeplex.com/license
//
// Some code in this file is based on a series of articles by David 
// Sackstein: http://blogs.microsoft.co.il/blogs/davids/archive/2008/12/20/msxml-in-c-but-as-elegant-as-c.aspx
//
//////////////////////////////////////////////////////////////////////

#pragma once

#define MAX_STRING_LENGTH 1024

#if _MSC_VER <= 1200 // Visual Studio 6
	#define strncpy_s(dest, src, size) strcpy (dest, src)
	#define vsprintf_s vsprintf
	#define wcsncpy_s wcsncpy
#endif

class ComInit
{
public:
	ComInit()  { ::CoInitialize(NULL); TRACE("COM initizalized\n"); }
	~ComInit() { ::CoUninitialize(); TRACE("COM uninitizalized\n"); }
};

class Error
{
	_TCHAR m_szMessage[512];

public:

Error (HRESULT hr);

//Error (PCTSTR format, ...);

Error (XmlParseError x);

Error (bool bIsSystemMsg, DWORD nID, ...);

Error (XmlParseError x, PCTSTR pczContext);

Error::Error(const Error& r)
{
	_tcscpy_s (m_szMessage, r.m_szMessage);
}

	operator LPCTSTR() { return m_szMessage; }
};

class StringWriter
{
	IStream *stream;

public:
	StringWriter ()
	{
		HRESULT hr = CreateStreamOnHGlobal (NULL, TRUE, &stream);
		if (FAILED(hr))
			throw Error (hr);
	}

	operator _variant_t() { return _variant_t(stream); }

	ULONG Write (_TCHAR* str, size_t count)
	{
		ULONG written;

		HRESULT hr = stream->Write(str, count, &written);
		if (FAILED(hr))
			throw Error (hr);

		return written;
	}

	LONGLONG Size ()
	{
		LARGE_INTEGER zero; zero.QuadPart = 0;
		ULARGE_INTEGER position;

		stream->Seek (zero, STREAM_SEEK_CUR, &position);
		return position.QuadPart;
	}

	ULONG ToString (_TCHAR* str, ULONG toRead)
	{
		LONGLONG maxRead = Size();

		if (toRead > maxRead)
			toRead = (ULONG) maxRead;

		LARGE_INTEGER zero; zero.QuadPart = 0;

		stream->Seek (zero, STREAM_SEEK_SET, NULL);
		
		ULONG read;
		stream->Read (str, toRead, &read);

		return read;
	}
};

CString FormatResourceString(DWORD dwStrID, ...);
CString FormatResourceString(DWORD dwStrID, va_list* args);

#include <set>
#include <algorithm>
typedef std::set<long> IndexSet;
typedef std::set<CString> GUIDSet;
typedef std::set<long>::const_iterator IndexSetInterator;

void merge_sets(IndexSet& set1, const IndexSet set2);